﻿/*
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * See product pages for more information.
 * http://closesudoku.codeplex.com
 * Copyright (C), 2011, hrondra
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

using Close.Classes;
using Fluid.Controls;

namespace Close.controls.FFluid
{
    public class GridButton : FlatButton
    {

        private bool[] _notes = { false, false, false, 
                                  false, false, false, 
                                  false, false, false};
        private char _value = ' ';
        private bool _imprinted = false;
        private bool _notesMode = false;

        public GridButton(string text)
            : base(text)
        {
            LightColor = Color.Black;
        }
        public GridButton()
            : base(string.Empty)
        {
            LightColor = Color.Black;
        }

        public string AllNotes
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                for (int ijk = 0; ijk < _notes.Length; ijk++)
                {
                    if (_notes[ijk])
                    {
                        sb.Append((ijk + 1).ToString());
                        sb.Append(" ");
                    }
                }
                if (sb.Length > 0)
                    sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }
        }


        /// <summary>
        /// Get notes  - every bit from left is number 1001 = 1
        /// </summary>
        public Int16 AllNotesInInt
        {
            get
            {
                Int16 returnValue = 0;
                for (int ijk = 0; ijk < _notes.Length; ijk++)
                {
                    if (_notes[ijk])
                    {
                        returnValue += (Int16)(Math.Pow(2, ijk));
                    }
                }
                return returnValue;
            }
            set
            {

                for (int ijk = 0; ijk < _notes.Length; ijk++)
                {
                    //_notes[ijk] = (value/ (Math.Pow(2, ijk)) == 1);
                    _notes[ijk] = (value & (short)(Math.Pow(2, ijk))) != 0;
                }
            }
        }

        /// <summary>
        /// Write note to policko - but without undo/redo functionality.
        /// </summary>
        /// <param name="value">value</param>
        /// <remarks>Only for load data from database - otherwise use SetNote</remarks>
        public void SetNoteWithoutHistory(Int16 num)
        {
            AllNotesInInt = num;
            this.Refresh();
        }

        /// <summary>
        /// Set/reset number in a notes.
        /// </summary>
        /// <param name="num">number to set</param>
        public void SetNote(int num)
        {
            RevertingChanges.UndoRedoHistory.Push(this.PositionRowColumn, AllNotesInInt, (Int16)num, true);
            if (num == 0)
                foreach (bool item in _notes)
                {
                    for (int ijk = 0; ijk < _notes.Length; ijk++)
                    {
                        _notes[ijk] = false;
                    }
                }
            else
                _notes[num - 1] = !_notes[num - 1];
        }


        /// <summary>
        /// Value which can not be modified.
        /// </summary>
        public char ImprintedValue
        {
            set
            {
                this._imprinted = true;
                _value = value;
            }
        }

        public bool Imprinted
        {
            get
            {
                return _imprinted;
            }
        }

        /// <summary>
        /// Write value to policko - but without undo/redo functionality.
        /// </summary>
        /// <param name="value">value</param>
        /// <remarks>Only for load data from database - otherwise use FaceValue</remarks>
        public void SetFaceValueWithoutHistory(char value)
        {
            if (!_imprinted)
                _value = value;
            else
                MyLog.Write(MyLog.LogType.Warning, "Attempt to rewrite imprinted value in init" + _value + value, string.Empty);
        }

        /// <summary>
        /// What is in the policko.
        /// </summary>
        public char FaceValue
        {
            set
            {
                if (!_imprinted)
                {
                    RevertingChanges.UndoRedoHistory.Push(this.PositionRowColumn, _value, value);
                    _value = value;
                }
                else
                    MyLog.Write(MyLog.LogType.Warning, "Attempt to rewrite imprinted value." + _value + value, string.Empty);
            }
            get
            {
                return _value;
            }

        }

        /// <summary>
        /// Write value to policko - after undo/redo.
        /// </summary>
        /// <param name="value">value</param>
        /// <remarks>Only for load data from undo/redo - otherwise use FaceValue</remarks>
        public void SetValueFromUndoRedo(Byte rowColumn, Int16 stepValue, char value, Int16 note, bool undo)
        {
            Int16 valueConverted = (Int16)(-1 * RevertingChanges.convertCharToByte(value));
            //set value
            if (stepValue == RevertingChanges.NothingInValue)
            {

                SetFaceValueWithoutHistory(' ');
            }
            else if (stepValue == 0)
            {
                SetNoteWithoutHistory(stepValue);
                valueConverted = note;
            }
            else if (stepValue < 0)
            {
                SetFaceValueWithoutHistory((char)(BitConverter.GetBytes(stepValue * -1)[0] + '0'));
                if (value == ' ')
                    valueConverted = RevertingChanges.NothingInValue;
            }
            else
            {
                SetNoteWithoutHistory(stepValue);
                valueConverted = note;
            }
            //Now modify history
            if(undo)
                RevertingChanges.UndoRedoHistory.UndoAfter(rowColumn, valueConverted, stepValue);
            else
                RevertingChanges.UndoRedoHistory.RedoAfter(rowColumn, valueConverted, stepValue);
        }


        /// <summary>
        /// Notes/SetPoint mode.
        /// </summary>
        public bool NotesMode
        {
            set
            {
                _notesMode = value;
            }
            get
            {
                return _notesMode;
            }

        }

        private bool _ConflictNumber = false;
        /// <summary>
        /// If true - will be show in different colour.
        /// </summary>
        public bool ConflictNumber
        {
            set
            {
                _ConflictNumber = value;
            }
        }

        private byte PositionRowColumn
        {
            //polickoRC
            get { return (byte)((this.Name[7] - '0') * 10 + this.Name[8] - '0'); }
        }



        protected override void PaintText(FluidPaintEventArgs e)
        {
            string bigText = FaceValue.ToString();

            Graphics g = e.Graphics;
            Rectangle r = e.ControlBounds;
            if (IsDown) r.Offset(ScaleX(1), ScaleY(1));
            stringFormat.Alignment = StringAlignment.Center;
            stringFormat.LineAlignment = StringAlignment.Center;

            SizeF bigSize = g.MeasureString(bigText, ThemeClass.bigFont);

            //int dw = (int)((this.Width - smallWidth) / 2f);
            //int dh = (int)(2f * e.ScaleFactor.Width);
            RectangleF rf = RectFFromRect(r);

            if (_imprinted)
            {
                Brush brushImprinted = _ConflictNumber ? new SolidBrush(ThemeClass.Settings.BoardForeColorConflict) : ThemeClass.Settings.BoardForeColorImprinted;
                g.DrawString(bigText, ThemeClass.bigFont, brushImprinted, rf, stringFormat);
            }
            else if (!string.IsNullOrEmpty(bigText) && bigText != " ")
            {
                Brush brush = IsDown ? new SolidBrush(ThemeClass.downTextbrush) : (_ConflictNumber ? new SolidBrush(ThemeClass.Settings.BoardForeColorConflict) : new SolidBrush(ThemeClass.textBrush));
                g.DrawString(bigText, ThemeClass.bigFont, brush, rf, stringFormat);
            }
            else
            {
                Brush brushSmall = IsDown ? ThemeClass.downTextbrushSmall : ThemeClass.textBrushSmall;
                string smallText = AllNotes;
                float smallWidth = string.IsNullOrEmpty(smallText) ? 0f : e.ScaleFactor.Width * 5f + g.MeasureString(smallText, ThemeClass.smallFont).Width;
                StringFormat stringFormatSmall = new StringFormat();
                rf.X += 1;
                float width = bigSize.Width + 4f * e.ScaleFactor.Width;
                g.DrawString(smallText, ThemeClass.smallFont, brushSmall, rf, stringFormatSmall);

            }
        }
        /*
        protected override void PaintButtonBackground(FluidPaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Rectangle rect = e.ControlBounds;

            if (this.Image != null)
            {
                int imW = ScaleX(this.Image.Width);
                int imH = ScaleY(this.Image.Height);

                int w = Math.Min(imW, this.Width);
                int h = Math.Min(imH, this.Height);
                rect.Width = w - 5;
                rect.Height = h - 5;
                rect.X += 2;
                rect.Y += 2;

                if (this.IsDown)
                {
                    rect.X++;
                    rect.Y++;
                }

                System.Drawing.Imaging.ImageAttributes attr = new System.Drawing.Imaging.ImageAttributes();
                //pruhledna
                attr.SetColorKey(Color.Fuchsia, Color.Fuchsia);

                g.DrawImage(this.Image, rect, 0, 0, this.Image.Width, this.Image.Height, GraphicsUnit.Pixel, attr);
            }

            base.PaintButtonBackground(e);
        }
        */

    }
}